using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Permissions;
using System.ServiceModel;
using PSE.Hosting.ServiceHoster.Business;
using PSE.Hosting.ServiceHoster.Services.FaultContracts;
using System.Threading;

namespace PSE.Hosting.ServiceHoster.Services
{
    /// <summary>
    /// 
    /// </summary>
    [ServiceBehavior(Name = "ServicesManager", Namespace = "http://www.bovespa.com.br/ServiceHoster.Service")]
    public class ServicesManager : ServiceContracts.IServicesManager
    {
        /// <summary>
        /// 
        /// </summary>
        public static void StartAll()
        {
            Business.Processes.ServiceHosterProcessManager.GetInstance().StartAll();
        }

        /// <summary>
        /// 
        /// </summary>
        public static void StopAll()
        {
            Business.Processes.ServiceHosterProcessManager.GetInstance().StopAll();
        }

        #region IServicesManager Members

        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void StartPackageAsynchronous(string packageName, bool startAssemblies)
        {
            Thread thread = new Thread(new ParameterizedThreadStart(this.StartPackageThread));
            object[] parameters = { packageName, startAssemblies };
            thread.Start(parameters);
        }

        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        private void StartPackageThread(object parameters)
        {
            object[] parameterArray = (object[])parameters;
            string packageName = parameterArray[0].ToString();
            bool startAssemblies = Convert.ToBoolean(parameterArray[1]);

            try
            {
                this.StartPackage(packageName, startAssemblies);
            }
            catch (FaultException<InvalidPackageFault>)
            {
                // Swallow the exception.
                // This is an asynchronous start, and the errors are not shown in the client.
            }
        }

        /// <summary>
        /// 
        /// </summary>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void StartPackage(string packageName, bool startAssemblies)
        {
            try
            {
                if (startAssemblies)
                {
                    Business.Processes.ServiceHosterProcessManager.GetInstance().StartAll(packageName);
                }
                else
                {
                    Business.Processes.ServiceHosterProcessManager.GetInstance().StartPackage(packageName);
                }
            }
            catch (InvalidPackageException ex)
            {
                InvalidPackageFault fault = new InvalidPackageFault();
                fault.Message = ex.Message;
                FaultReason reason = new FaultReason(ex.Message);

                throw new FaultException<InvalidPackageFault>(fault, reason); 
            }
        }

        /// <summary>
        /// Stops all WCF services from a specific package.
        /// </summary>
        /// <param name="package">The name of the package.</param>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void StopPackage(string package, bool save)
        {
            if (save)
            {
                Business.Processes.ServiceHosterProcessManager.GetInstance().StopAll(package);
            }
            else
            {
                Business.Processes.ServiceHosterProcessManager.GetInstance().StopPackage(package);
            }
        }

        /// <summary>
        /// Stops all WCF services from a specific assembly.
        /// </summary>
        /// <param name="packageName">The name of the package of the assembly to start.</param>
        /// <param name="fileName">The name of the assembly file to start. This is the filename only, without the path.</param>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void StartAssembly(string packageName, string fileName)
        {
            try
            {
                Business.Processes.ServiceHosterProcessManager.GetInstance().StartAssembly(packageName, fileName);
            }
            catch (InvalidAssemblyException ex)
            {
                InvalidAssemblyFault fault = new InvalidAssemblyFault();
                fault.Message = ex.Message;
                FaultReason reason = new FaultReason(ex.Message);

                throw new FaultException<InvalidAssemblyFault>(fault, reason); 
            }
        }

        /// <summary>
        /// Start all WCF services from a specific assembly.
        /// </summary>
        /// <param name="packageName">The name of the package.</param>
        /// <param name="codeBase"></param>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void StopAssembly(string packageName, string codeBase)
        {
            Business.Processes.ServiceHosterProcessManager.GetInstance().StopAssembly(packageName, codeBase);
        }

        /// <summary>
        /// Adds a new package to hold WCF assemblies.
        /// </summary>
        /// <param name="packageName"></param>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void AddPackage(string packageName, string domain, string userName, string password)
        {
            try
            {
                Business.Processes.ServiceHosterProcessManager.GetInstance().AddPackage(packageName, domain, userName, password);
            }
            catch (PackageAlreadyExistsException ex)
            {
                PackageAlreadyExistsFault fault = new PackageAlreadyExistsFault();
                fault.Message = ex.Message;
                FaultReason reason = new FaultReason(ex.Message);

                throw new FaultException<PackageAlreadyExistsFault>(fault, reason); 
            }
        }

        /// <summary>
        /// Removes a package from the server.
        /// </summary>
        /// <param name="packageName">The name of the package to be removed.</param>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void UpdatePackage(string packageName, string domain, string userName, string password)
        {
            try
            {
                Business.Processes.ServiceHosterProcessManager.GetInstance().UpdatePackage(packageName, domain, userName, password);
            }
            catch (InvalidPackageException ex)
            {
                InvalidPackageFault fault = new InvalidPackageFault();
                fault.Message = ex.Message;
                FaultReason reason = new FaultReason(ex.Message);

                throw new FaultException<InvalidPackageFault>(fault, reason);
            }
        }

        /// <summary>
        /// Removes a package from the server.
        /// </summary>
        /// <param name="packageName">The name of the package to be removed.</param>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void RemovePackage(string packageName)
        {
            try
            {
                Business.Processes.ServiceHosterProcessManager.GetInstance().RemovePackage(packageName);
            }
            catch (InvalidPackageException ex)
            {
                InvalidPackageFault fault = new InvalidPackageFault();
                fault.Message = ex.Message;
                FaultReason reason = new FaultReason(ex.Message);

                throw new FaultException<InvalidPackageFault>(fault, reason); 
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void AddAssembly(DataContracts.AssemblyRequest request)
        {
            try
            {
                Business.Processes.ServiceHosterProcessManager.GetInstance().AddAssembly(request.PackageName, request.CodeBase);
            }
            catch (ArgumentException ex)
            {
                InvalidParameterFault fault = new InvalidParameterFault();
                fault.Message = ex.Message;
                fault.Parameter = ex.ParamName;
                FaultReason reason = new FaultReason(ex.Message);

                throw new FaultException<InvalidParameterFault>(fault, reason);
            }
        }

        /// <summary>
        /// Removes an WCF assembly from ServiceManager.
        /// </summary>
        /// <param name="packageName"></param>
        /// <param name="assembly"></param>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void RemoveAssembly(string packageName, string assembly)
        {
            Business.Processes.ServiceHosterProcessManager.GetInstance().RemoveAssembly(packageName, assembly);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void Remove(System.String packageName, System.String serviceName)
        {
            Business.Processes.ServiceHosterProcessManager.GetInstance().RemoveAssembly(packageName, serviceName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void Start(DataContracts.ServiceIdentifier request)
        {
            Business.Processes.ServiceHosterProcessManager.GetInstance().StartService(request.PackageName, request.Assembly, request.ServiceName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void Stop(DataContracts.ServiceIdentifier request)
        {
            Business.Processes.ServiceHosterProcessManager.GetInstance().StopService(request.PackageName, request.Assembly, request.ServiceName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public DataContracts.ServiceList GetServicesList(string packageName, string fileName)
        {
            List<Entities.Service> services = Business.Processes.ServiceHosterProcessManager.GetInstance().GetServiceList(packageName, fileName);
            DataContracts.ServiceList response = new DataContracts.ServiceList();
            response.Services = new List<DataContracts.Service>(services.Count);

            foreach (Entities.Service service in services)
            {
                response.Services.Add(ServiceTranslation.ToDataContract(service));
            }

            return response;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public DataContracts.PackageList GetPackageList()
        {
            List<Entities.Package> packages = Business.Processes.ServiceHosterProcessManager.GetInstance().GetPackageList();
            DataContracts.PackageList response = new DataContracts.PackageList();
            response.Packages = new List<DataContracts.Package>(packages.Count);

            foreach (Entities.Package package in packages)
            {
                response.Packages.Add(PackageTranslation.ToDataContract(package));
            }

            return response;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="packageName"></param>
        /// <returns></returns>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public DataContracts.AssemblyList GetAssemblyList(string packageName)
        {
            List<Entities.Assembly> assemblies = Business.Processes.ServiceHosterProcessManager.GetInstance().GetAssemblyList(packageName);
            DataContracts.AssemblyList response = new DataContracts.AssemblyList();
            response.Assemblies = new List<DataContracts.Assembly>(assemblies.Count);

            foreach (Entities.Assembly assembly in assemblies)
            {
                response.Assemblies.Add(AssemblyTranslation.ToDataContract(assembly));
            }

            return response;
        }

        /// <summary>
        /// 
        /// </summary>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void StartWindowsService(bool asynchronous, bool startAll)
        {
            Business.Processes.ServiceHosterProcessManager.GetInstance().StartWindowsService(asynchronous, startAll);
        }

        /// <summary>
        /// 
        /// </summary>
        [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        [PrincipalPermission(SecurityAction.Demand, Role = "Administradores")]
        [PrincipalPermission(SecurityAction.Demand, Role = "WCF Services Managers")]
        public void StopWindowsService()
        {
            Business.Processes.ServiceHosterProcessManager.GetInstance().StopWindowsService();
        }

        #endregion
    }
}
